/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ControllerSerialization;

import ButtonBeans.ButtonBean;
import ButtonBeans.ControllerElement;
import ButtonBeans.JoystickBean;
import ButtonBeans.MouseJoystickBean;
import ButtonBeans.RoundButtonBean;
import GameControllerExceptions.InvalidButtonCountException;
import GameControllerExceptions.InvalidControllerException;
import Helper.ControllerValidator;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import controllerButtons.MouseJoystickButton;
import controllerButtons.NormalControllerButton;
import controllerButtons.RoundControllerButton;
import controllerButtons.StaticControllerButton;
import java.awt.Component;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JLayeredPane;

/**
 *
 * @author luc0
 */
public class ControllerSerializer {

    private static ControllerSerializer instance;
    private String xml;
    List<ControllerElement> buttonList;

    private ControllerSerializer() {
    }

    public static ControllerSerializer getInstance() {
        if (instance == null) {
            instance = new ControllerSerializer();
        }
        return instance;
    }

    public void savaController(JLayeredPane controllerPanel, String location) throws InvalidControllerException, InvalidButtonCountException {

//        if (controllerPanel.getComponentCount() == 2) {
//            throw new InvalidButtonCountException();
//        }
        Component[] components = controllerPanel.getComponents();
        List<ControllerElement> buttonToSaveList = new ArrayList<ControllerElement>();
        int buttonId = 0;
        for (int i = 0; i < components.length; i++) {
            if (components[i] instanceof RoundControllerButton) {
                RoundButtonBean bean = new RoundButtonBean();
                RoundControllerButton button = (RoundControllerButton) components[i];

                bean.setLx(button.getLocation().x);
                bean.setLy(button.getLocation().y);
                bean.setLabel(button.getLabel());
                bean.setHeight(button.getHeight());
                bean.setLabel(button.getLabel());
                bean.setColor(button.getColor());
                bean.setButtonId(buttonId);
                bean.setButtonToPress(button.getButtonToPress());
                bean.setRepeatsPresses(button.isRepeatsPresses());
                bean.setTimeBetweenPresses(button.getTimeBetweePresses());
                buttonToSaveList.add(bean);
            } else if (components[i] instanceof StaticControllerButton) {
                JoystickBean bean = new JoystickBean();
                StaticControllerButton button = (StaticControllerButton) components[i];
                bean.setColor(button.getColor());
                bean.setLx(button.getLocation().x);
                bean.setLy(button.getLocation().y);
                bean.setWidth(button.getWidth());
                bean.setHeight(button.getHeight());
                bean.setButtonId(buttonId);
                bean.setUpButton(button.getUpButton());
                bean.setDownButton(button.getDownButton());
                bean.setLeftButton(button.getLeftButton());
                bean.setRightButton(button.getRightButton());
                buttonToSaveList.add(bean);

            } else if (components[i] instanceof NormalControllerButton) {
                ButtonBean bean = new ButtonBean();
                NormalControllerButton button = (NormalControllerButton) components[i];
                bean.setColor(button.getColor());
                bean.setLabel(button.getText());
                bean.setLx(button.getLocation().x);
                bean.setLy(button.getLocation().y);
                bean.setHeight(button.getHeight());
                bean.setWidth(button.getWidth());
                bean.setButtonId(buttonId);
                bean.setButtonToPress(button.getButtonToPress());
                buttonToSaveList.add(bean);
            } else if(components[i] instanceof MouseJoystickButton){
                MouseJoystickBean bean = new MouseJoystickBean();
                MouseJoystickButton button = (MouseJoystickButton) components[i];
                bean.setLx(button.getLocation().x);
                bean.setLy(button.getLocation().y);
                bean.setHeight(button.getHeight());
                bean.setWidth(button.getWidth());
                bean.setButtonId(buttonId);
                buttonToSaveList.add(bean);
            }
            buttonId++;
        }

        ControllerValidator validator = ControllerValidator.getInstance();
        if (!validator.isControllerValid(buttonToSaveList)) {
            throw new InvalidControllerException();
        }

        try {
            FileOutputStream outputStream = new FileOutputStream(new File(location));
            OutputStreamWriter writer = new OutputStreamWriter(outputStream, Charset.forName("UTF-8")); // UTF-8 , Charset.forName("UTF-16 ")
            XStream xstream = new XStream(new DomDriver("UTF-8")); //"UTF-8"
            xstream.toXML(buttonToSaveList, writer);


            outputStream.flush();
            outputStream.close();
            writer.close();

        } catch (IOException e) {
        } finally {
        }


    }

    public List<ControllerElement> loadController(File file) throws InvalidControllerException {
        XStream xstream = new XStream(new DomDriver());

        byte[] buffer = new byte[(int) new File(file.getAbsolutePath()).length()];
        FileInputStream f;
        try {
            f = new FileInputStream(file.getAbsolutePath());
            f.read(buffer);


            xml = new String(buffer);
            try {
                buttonList = (ArrayList) xstream.fromXML(xml);
            } catch (Exception ex) {
                throw new InvalidControllerException();
            }


            f.close();

        } catch (IOException ex) {
            Logger.getLogger(ControllerSerializer.class.getName()).log(Level.SEVERE, null, ex);
        }
        ControllerValidator controllerValidator = ControllerValidator.getInstance();
        if (!controllerValidator.isControllerValid(buttonList)) {
            throw new InvalidControllerException();
        }

        return buttonList;
    }

    public List<ControllerElement> getButtonList() {
        return buttonList;
    }

    public String getControllerAsString() {
        return xml;
    }
}
